import 'package:dio/dio.dart';
import 'package:dio_test/src/utils.dart';

import '../DioExtens.dart';
import '../common/test_page.dart';

class RequestIntegrationTestPage extends TestPage {
  RequestIntegrationTestPage(super.title) {
    group('requests', () {
      late Dio dio;

      group('restful APIs', () {
        const data = {'content': 'I am payload'};

        test('dio.head()', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.head(
            '/anything',
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
        });

        test('dio.get()', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.get(
            '/get',
            queryParameters: {'id': '12', 'name': 'wendu'},
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'GET');
          expect(response.data['args'], {'id': '12', 'name': 'wendu'});
        });

        // TODO This is not supported on web, should we warn?
        test('dio.get()获取指定内容', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.get(
            '/anything',
            queryParameters: {'id': '12', 'name': 'wendu'},
            data: data,
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'GET');
          expect(response.data['args'], {'id': '12', 'name': 'wendu'});
          expect(response.data['json'], data);
          expect(
            response.data['headers']['Content-Type'],
            Headers.jsonContentType,
          );
        });

        test('dio.post()', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.post(
            '/post',
            data: data,
            options: Options(contentType: Headers.jsonContentType),
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'POST');
          expect(response.data['json'], data);
          expect(
            response.data['headers']['Content-Type'],
            Headers.jsonContentType,
          );
        });

        test('dio.put()', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.put(
            '/put',
            data: data,
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'PUT');
          expect(response.data['json'], data);
          expect(
            response.data['headers']['Content-Type'],
            Headers.jsonContentType,
          );
        });

        test('dio.patch()', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.patch(
            '/patch',
            data: data,
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'PATCH');
          expect(response.data['json'], data);
          expect(
            response.data['headers']['Content-Type'],
            Headers.jsonContentType,
          );
        });

        test('dio.delete()', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.delete(
            '/delete',
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'DELETE');
        });

        test('dio.delete() 带有data参数', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.delete(
            '/delete',
            data: data,
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'DELETE');
          expect(response.data['json'], data);
          expect(
            response.data['headers']['Content-Type'],
            Headers.jsonContentType,
          );
        });
      });

      group('dio.headUri(Uri.parse("/anything"))', () {
        dio = getDio();
        dio.options.baseUrl = 'https://httpbun.com/';
        const data = {'content': 'I am payload'};

        test('HEAD', () async {
          final response = await dio.headUri(
            Uri.parse('/anything'),
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
        });

        test('dio.getUri(Uri(path: "/get", queryParameters: {"id": "12", "name": "wendu"}))', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.getUri(
            Uri(path: '/get', queryParameters: {'id': '12', 'name': 'wendu'}),
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['args'], {'id': '12', 'name': 'wendu'});
        });

        // Not supported on web
        test('dio.getUri() 带有data参数的请求', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.getUri(
            Uri(
              path: '/anything',
              queryParameters: {'id': '12', 'name': 'wendu'},
            ),
            data: data,
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['args'], {'id': '12', 'name': 'wendu'});
          expect(response.data['json'], data);
          expect(
            response.data['headers']['Content-Type'],
            Headers.jsonContentType,
          );
        });

        test('dio.postUri()', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.postUri(
            Uri.parse('/post'),
            data: data,
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'POST');
          expect(response.data['json'], data);
          expect(
            response.data['headers']['Content-Type'],
            Headers.jsonContentType,
          );
        });

        test('dio.putUri()', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.putUri(
            Uri.parse('/put'),
            data: data,
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'PUT');
          expect(response.data['json'], data);
          expect(
            response.data['headers']['Content-Type'],
            Headers.jsonContentType,
          );
        });

        test('dio.patchUri()', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.patchUri(
            Uri.parse('/patch'),
            data: data,
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'PATCH');
          expect(response.data['json'], data);
          expect(
            response.data['headers']['Content-Type'],
            Headers.jsonContentType,
          );
        });

        test('dio.deleteUri()', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.deleteUri(
            Uri.parse('/delete'),
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'DELETE');
        });

        test('dio.deleteUri() 带有参数data测试', () async {
          dio = getDio();
          dio.options.baseUrl = 'https://httpbun.com/';
          final response = await dio.deleteUri(
            Uri.parse('/delete'),
            data: data,
          );
          expect(response.statusCode, 200);
          expect(response.isRedirect, 'isFalse');
          expect(response.data['method'], 'DELETE');
          expect(response.data['json'], data);
          expect(
            response.data['headers']['Content-Type'],
            Headers.jsonContentType,
          );
        });
      });

      group('redirects', () {
        test('dio.get(url, queryParameters:{}) 改变get的url', () async {
          final response = await dio.get(
            '/redirect',
            queryParameters: {'url': 'https://httpbun.com/get'},
            onReceiveProgress: (received, total) {
            },
          );
          expect(response.isRedirect, 'isTrue');

          if (!isWeb) {
            expect(response.redirects.length, 1);
            final ri = response.redirects.first;
            expect(ri.statusCode, 302);
            expect(ri.location.path, '/get');
            expect(ri.method, 'GET');
          }
        });

        test('dio.get获取多配置', () async {
          final response = await dio.get(
            '/redirect/3',
          );
          expect(response.isRedirect, 'isTrue');

          if (!isWeb) {
            // Redirects are not supported in web.
            // Rhe browser will follow the redirects automatically.
            expect(response.redirects.length, 3);
            final ri = response.redirects.first;
            expect(ri.statusCode, 302);
            expect(ri.method, 'GET');
          }
        });
      });

      group('验证dio方法可获取的状态代码', () {
        for (final code in [400, 401, 404, 500, 503]) {
          test('$code', () async {
            expect(
              dio.get('/status/$code').catchError(
                      (e) => throw (e as DioException).response!.statusCode!),
              code,
            );
          });
        }
      });

      test('dio.get(url, options: Options(headers: {key: {value1, value2}}))', () async {
        final Response response = await dio.get(
          '/get',
          options: Options(
            headers: {
              'x-multi-value-request-header': ['value1', 'value2'],
            },
          ),
        );
        expect(response.statusCode, 200);
        expect(response.isRedirect, 'isFalse');
        expect(
          response.data['headers']['X-Multi-Value-Request-Header'],
          // TODO we have a diff here between browser and non-browser
          ('value1, value2'),
        );
      });

      group('generic parameters', () {
        test('dio.get("/get")', () async {
          final response = await dio.get('/get');
          expect(response.data, '');
          expect(response.data, 'isNotEmpty');
        });

        test('dio.get<Map>("/get")', () async {
          final response = await dio.get<Map>('/get');
          expect(response.data, '');
          expect(response.data, 'isNotEmpty');
        });

        test('dio.get<String>("/get")', () async {
          final response = await dio.get<String>('/get');
          expect(response.data, '');
          expect(response.data, 'isNotEmpty');
        });

        test('dio.post<List>()', () async {
          final response = await dio.post<List>(
            '/payload',
            data: '[1,2,3]',
          );
          expect(response.data, '');
          expect(response.data, 'isNotEmpty');
          expect(response.data![0], 1);
        });
      });
    });
  }

}